#include "RenderMesh.h"
#include "SceneNode.h"

namespace Nezha
{
	RenderMesh::RenderMesh(GeometryData* gd)
		:mGeometryDataPtr(gd)
		,mVBAccessor(NULL)
		,mSceneNode(NULL)
	{

	}

	RenderMesh::~RenderMesh()
	{
		if(mVBAccessor)
		{
			NZ_Delete mVBAccessor;
		}

		mGeometryDataPtr = NULL;
	}

	void RenderMesh::_setSceneHierarchy(SceneNode* sn)
	{
		mSceneNode = sn;
	}

	void RenderMesh::_setAABB(const AABB& aabb)
	{
		mBounding = aabb;
	}

	const _string& RenderMesh::getROName() const
	{
		return mSceneNode ? mSceneNode->getName() : StringUtil::Blank;
	}

	void RenderMesh::prepareGeometry4Pipeline(GeometryDataBatch& batch)
	{
		if(!mGeometryDataPtr)
		{
			batch.clear();
		}
		else
		{
			u32 numVerts = mGeometryDataPtr->getNumVertex();
			u32 numIndices = mGeometryDataPtr->getNumIndices();

			batch.createBatch(0, 0, numVerts, numIndices, mGeometryDataPtr);
		}
	}

	u32 RenderMesh::getGeometryHash() const
	{
		return (u32)mGeometryDataPtr.ptr();
	}

	VertexBufferAccessor* RenderMesh::beginAccess()
	{
		if(!mVBAccessor)
		{
			mVBAccessor = NZ_New VertexBufferAccessor();
		}

		if(mGeometryDataPtr.ptr())
		{
			if(mVBAccessor->accessProcessing())
			{
				return NULL;
			}

			if(mVBAccessor->beginAccess(mGeometryDataPtr))
			{
				return mVBAccessor;
			}
		}

		return NULL;
	}

	void RenderMesh::endAccess()
	{
		if(mVBAccessor && mVBAccessor->accessProcessing())
		{
			mVBAccessor->endAccess();
		}
	}

	const AABB& RenderMesh::recaculateBounding()
	{
		VertexBufferAccessor* vba = beginAccess();

		if(vba)
		{
			const VertexBufferAccessor::VertexElemBinding* veb = vba->getElemBindingByVS(VS_POSITION);

			if(veb)
			{
				u8* data = (u8*)vba->_accessVertexs();
				u32 offset = ((u8*)veb->Data) - data;
				mBounding.fromVertexsData(mGeometryDataPtr->getNumVertex(), offset, veb->BufferStride, data);
			}
			else
			{
				NZError("Mesh <RO, %s> has no position data.", getROName().c_str());
			}

			vba->endAccess();
		}

		return mBounding;
	}
}